package com.honghu.cloud.tools.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.honghu.cloud.utils.Exceptions;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * SFTP发送报文文件 SFTP下载报文文件
 * @author Administrator
 *
 */
public class SFtpUtil {
	
	private static Logger logger = LoggerFactory.getLogger(SFtpUtil.class);
	
	// ftp客户端对象
	//private static ChannelSftp sftp = null;
	private static ChannelExec exec;
	private static Properties sshConfig = null;
	
	static{
		sshConfig = new Properties();
		sshConfig.put("userauth.gssapi-with-mic", "no");
		sshConfig.put("StrictHostKeyChecking", "no");
	}
	/**
	 * sftp连接函数
	 * @param server ftp server 端IP
	 * @param port 端口
	 * @param user 用户名
	 * @param password 密码
	 * @return boolean
	 */
	public static ChannelSftp connect(String host, int port, String username,
			String password) {
//		if(sftp!=null && sftp.isConnected()){
//			return true;
//		}
		ChannelSftp sftp = null;
		try {
			JSch jsch = new JSch();
			jsch.getSession(username, host, port);
			Session sshSession = jsch.getSession(username, host, port);
			sshSession.setPassword(password);
			sshSession.setConfig(sshConfig);
			sshSession.setTimeout(30*1000); // 设置超时时间为30秒
			sshSession.connect();
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			sftp = (ChannelSftp) channel;
		} catch (Exception e) {
			logger.error("connect异常："+Exceptions.getStackTraceAsString(e));
			return sftp;
		}
		return sftp;
	}

	
	/**
	 * Sftp文件上传
	 * @param sFilePath 源文件路径
	 * @param sFileName 源文件名称
	 * @param dFilePath 目标文件路径
	 * @param dFileName 目标文件名称
	 * @param type 传输类型
	 * @return boolean
	 */
	public static boolean uploadFile(ChannelSftp sftp,String sFilePath, String sFileName,
			String dFilePath, String dFileName, String type) {
		FileInputStream is = null;
		try {
			sftp.cd(dFilePath);
			File file = new File(sFilePath + sFileName);
			is = new FileInputStream(file);
			sftp.put(is, file.getName());
			if (!sFileName.equals(dFileName)) {
				sftp.rename(sFileName, dFileName);
			}
		} catch (Exception e) {
			logger.error("uploadFile异常："+Exceptions.getStackTraceAsString(e));
			return false;
		}finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
				}
			}
			SFtpUtil.close(sftp);
		}
		return true;
	}

	
	/**
	 * 上传文件
	 * @param directory 上传的目录
	 * @param uploadFile 要上传的文件
	 * @param sftp
	 */
	public static Boolean upload(ChannelSftp sftp, String directory, String uploadFile) {
		FileInputStream is = null;
		try {
			
			try {
				//这里需要注意:windows中的斜杠\在linux中识别不了,干,必须转换一下,通常会出现问题是因为测试、开发用的win
				//在linux中新建文件夹就不管用了
				
				directory = directory.replaceAll("\\\\", "/");
				
				sftp.cd(directory);
				
			} catch (Exception e) {
					// logger.error("ftp打开文件异常："+e.getMessage()+",/分割路径，单个打开文件夹。");
				    String[] folders = directory.split( "/" );
				    for ( String folder : folders ) {  
				        if ( folder.length() > 0 ) {  
				            try {  
				                sftp.cd( folder );
				            }  
				            catch ( SftpException e1 ) {  
				            	// logger.error("单个进入下级文件夹异常："+e.getMessage());
				                sftp.mkdir( folder );
				                sftp.cd( folder );
				            }  
				        }  
				    }
			}
			File file = new File(uploadFile);
			is = new FileInputStream(file);
			sftp.put(is, file.getName());
			
		} catch (Exception e) {
			logger.error("upload异常："+Exceptions.getStackTraceAsString(e));
			return false;
		}finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
				}
			}
			SFtpUtil.close(sftp);
		}
		return true;
	}

	
	/**
	 * 上传文件
	 * @param in 文件流
	 * @param directory 上传的目录
	 * @param fileName 文件名称，如：file.jpg
	 * @param sftp
	 */
	public static boolean upload(ChannelSftp sftp, InputStream in, String directory, String fileName) {
		try {
			
			try {
				//这里需要注意:windows中的斜杠\在linux中识别不了,干,必须转换一下,通常会出现问题是因为测试、开发用的win
				//在linux中新建文件夹就不管用了
				directory = directory.replaceAll("\\\\", "/");
				sftp.cd(directory);
			} catch (Exception e) {
				String[] folders = directory.split( "/" );
			    for ( String folder : folders ) {  
			        if ( folder.length() > 0 ) {  
			            try {  
			                sftp.cd( folder );
			            }  
			            catch ( SftpException e1 ) {  
			                sftp.mkdir( folder );
			                sftp.cd( folder );
			            }  
			        }  
			    }
			}
			sftp.put(in, fileName);
		} catch (Exception e) {
			logger.error("ftp上传文件失败："+Exceptions.getStackTraceAsString(e));
			return false;
		}finally {
			try {
				if(in != null){
					in.close();
				}
			} catch (IOException e) {
			}
			SFtpUtil.close(sftp);
		}
		return true;
	}
	
	/**
	 * ftp下载文件
	 * @param sFilePath 源文件路径
	 * @param sFileName 源文件名称
	 * @param dFilePath 目标文件路径
	 * @param dFileName 目标文件名称
	 * @param type 传输类型
	 * @return boolean
	 */
	public static boolean downloadFile(ChannelSftp sftp, String sFilePath, String sFileName,
			String dFilePath, String dFileName, String type) {
		OutputStream os = null;
		try {
			sftp.cd(sFilePath);
			File file = new File(dFilePath + dFileName);
			os = new FileOutputStream(file);
			sftp.get(sFileName, os);
			os.close();
		} catch (Exception e) {
			logger.error("downloadFile异常："+Exceptions.getStackTraceAsString(e));
			return false;
		}finally {
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
				}
			}
			SFtpUtil.close(sftp);
		}
		return true;
	}


	/**
	 * 执行一次shell命令，之后连接就关闭
	 * @param cmd
	 * @return
	 * @throws Exception
	 */
	public static int runCmd(ChannelSftp sftp, String cmd) {
		try {
			exec = (ChannelExec) sftp.getSession().openChannel("exec");
			exec.setCommand(cmd);
			exec.setInputStream(null);
			exec.setErrStream(System.err);
			InputStream in = exec.getInputStream();
			exec.connect();
			int res = -1;
			StringBuffer buf = new StringBuffer(1024);
			byte[] tmp = new byte[1024];
			while (true) {
				while (in.available() > 0) {
					int i = in.read(tmp, 0, 1024);
					if (i < 0)
						break;
					buf.append(new String(tmp, 0, i));
				}
				if (exec.isClosed()) {
					res = exec.getExitStatus();
					break;
				}
			}
			exec.disconnect();
			return res;
		} catch (Exception e) {
			logger.error("runCmd异常："+Exceptions.getStackTraceAsString(e));
			throw new RuntimeException(e);
		}finally{
			if(exec != null){
				exec.disconnect();
			}
			SFtpUtil.close(sftp);
		}
	}
	
	
    public static boolean makeDirs(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return false;
        }
        
        File folder = new File(filePath);
        return (folder.exists() && folder.isDirectory()) ? true : folder.mkdirs();
    }
	
    
	/**
	 * 关闭ftp连接
	 * @return boolean
	 */
	public static boolean close(ChannelSftp sftp) {
		if (sftp != null) {
			// 关闭当前连接的session
			try {
				Session session = sftp.getSession();
				if(session != null){
					session.disconnect();
				}
			} catch (JSchException e1) {
				logger.error("ftp seesion关闭异常："+Exceptions.getStackTraceAsString(e1));
			}
			try {
				sftp.disconnect();
				sftp = null;
			} catch (Exception e) {
				logger.error("close异常："+Exceptions.getStackTraceAsString(e));
				throw new RuntimeException(e);
			}
		}
		return true;
	}

	
	/**
	 * 列出目录下的文件
	 * @param sFilePath 要列出的目录
	 * @param sftp
	 * @return
	 * @throws SftpException
	 */
	@SuppressWarnings("rawtypes")
	public static Vector listFiles(ChannelSftp sftp, String sFilePath) throws SftpException {
		return sftp.ls(sFilePath);
	}
	
	/*public static void testmai(String[] args) {
		
//        System.out.println(flag);
//        runCmd("mkdir -p /mnt/images/test/file/image");
        upload("/upload/aaaaa", "D:\\b2b2c\\favicon.ico");
//        downloadFile("/mnt/images/test/file/image", "license.zip", "c:\\", "license.zip", "");
        
//        close();
		
//		makeDirs("g:\\b2b2c\\abcde\\sfd\\sf\\ds\\f\\d\\s\\fds");
		
		
	}*/
}
